TypeScript Transformerを使って任意の構文木を書き換えるシンプルなWebアプリの例
やりたいこと
実際に動作するリポジトリ
https://gh-card.dev/repos/nwtgck/typescript-transformer-prac-web.svg https://github.com/nwtgck/typescript-transformer-prac-web
npm run serverした後ににアクセスすれば動作が確認できる。 やりかた
上記の資料でも触れられているがtsconfig.jsonでCustom Transformersを指定すること現状ができない。
ttypescriptを使うことでtsconfig.jsonで指定できるようになるようだが変わったことをすると後でハマったり融通が利かなくなる経験則があるので避けた。 code:transformers/my-transformer.ts
import * as ts from 'typescript';
// Transformer for alert("...") => console.log("alert: ..."); export default function (ctx: ts.TransformationContext) {
function visitNode(node: ts.Node): ts.Node {
if (!isAlert(node)) {
return ts.visitEachChild(node, visitNode, ctx);
}
return createHelper(node);
}
function createHelper(node: ts.Node) {
ctx.requestEmitHelper({
name: "ts:say",
priority: 0,
scoped: false,
text: "var __alert_console__ = function(msg) { console.log('alert: ' + msg); };", });
return ts.setTextRange(ts.createIdentifier("__alert_console__" ), node);
}
function isAlert(node: ts.Node): node is ts.PropertyAccessExpression {
return node.kind === ts.SyntaxKind.Identifier && node.getText() === "alert";
}
return (source: ts.SourceFile) => ts.updateSourceFileNode(source, ts.visitNodes(source.statements, visitNode));
}
以下のようにtsc transformers/*.tsでtransformers/*.jsとして配置されるようにあらかじめビルドされるようにしている。
code:package.json
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build-transformers": "tsc transformers/*.ts",
"serve": "npm run build-transformers && webpack-dev-server --watch",
"build": "npm run build-transformers && webpack"
....
code:webpack.config.js
// 自分のTransformerをインポート
const mytransformer = require('./transformers/my-transformer').default;
...
module.exports = {
...
module: {
rules: [
...
{
test: /\.ts$/,
exclude: /node_modules/,
loader: 'ts-loader',
// 以下を追記
options: {
getCustomTransformers: () => ({
}),
transpileOnly: true,
},
}
]
},
...
main.tsでalert()を使った何かを書く。
code:main.ts
...
alert("hello, world");
実際の変更のコミット
実際の動作
alert()しているがalertされずにコンソールに出力されていることが確認できる。
https://gyazo.com/d0f923de11ab7ccf6aee2fc81dd83c20
その他の参考にした資料
おまけ
以下(おそらくソースマップ)を見るとalert()のままになっている。変換後のTypeScriptだとよかったのだが。これだとデバッグ時はすごく困難な気がする。 https://gyazo.com/1b0886897f10f16b0d533d7d925d016c